#include "headers/keyboard.h"
#include "../tools/headers/common.h"
#include "../api/headers/io.h"
#include "../interrupts/headers/idt.h"
#include "../interrupts/headers/irq.h"
#include "../multitasking/headers/task.h"
#include "../adt/headers/queue.h"
extern task_t *task_list;
extern task_t *current_task;
extern task_t *focused_task;
void makeVirtualConsoleFocused(task_t* task);
#define F1 230
#define F2 231
#define F3 232
#define F4 233
#define F5 234
#define F6 235
#define F7 236
#define F8 237
#define F9 238
#define F10 239
#define ESC 240
#define DELETE 241

u8int keyboard_layout_us_uppercase[128] =
{
	ESC /*Esc*/,  27, '!', '@', '#', '$', '%', '^', '&', '*', '(',
	')', '_', '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T',
	'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, //Ctrl
  	'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
 	'|', '~', 0, //Left Shift
 	'\\', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>',
	'?', 0, //Right Shift
  	'*', 0,	// Alt
  	' ', //Space Bar
    0, //Caps Lock
	F1, //F1 ...
    F2, F3, F4, F5, F6, F7, F8, F9,
    F10,	// ... F10
    0, //Num Lock
    0, //Scroll Lock
    0, //Home
    0, //Up Arrow
    0, //Page Up
  	'-', 0, //Left Arrow
    0, 0, //Right Arrow
  	'+', 0,	//End
    0, //Down Arrow
    0, //Page Down
    0, // Insert
    DELETE, //Delete
    0, 0, 0,
    0, //F11
    0, //F12
    0, //All other keys are undefined
};

u8int keyboard_layout_us_lowercase[128] =
{
	ESC,  27, '1', '2', '3', '4', '5', '6', '7', '8', '9',
	'0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't',
	'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, //Ctrl
  	'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
 	'\'', '`', 0, //Left Shift
 	'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.',
	'/', 0, //Right Shift
  	'*', 0,	// Alt
  	' ', //Space Bar
    0, //Caps Lock
    F1, //F1 ...
    F2, F3, F4, F5, F6, F7, F8, F9,
    F10,	// ... F10
    0, //Num Lock
    0, //Scroll Lock
    0, //Home
    0, //Up Arrow
    0, //Page Up
  	'-', 0, //Left Arrow
    0, 0, //Right Arrow
  	'+', 0,	//End
    0, //Down Arrow
    0, //Page Down
    0, // Insert
    DELETE, //Delete
    0, 0, 0,
    0, //F11
    0, //F12
    0, //All other keys are undefined
};



#define NUM_LOCK 2
#define SCROLL_LOCK 1
#define CAPS_LOCK 4
#define SHIFT 1
#define CTRL 2
#define ALT 4

u8int led_status = 0;
u8int control_keys_status = 0;

void keyboard_handler(registers_type registers);
void set_leds();
void set_typematic_info();

void install_keyboard()
{
	//set_typematic_info();
	register_interrupt_handler(IRQ1, keyboard_handler);
	
}

void keyboard_handler(registers_type registers)
{
    u8int scancode = inb(0x60);
	u8int key = 0;
	//if(!(scancode & 0x80))
		//printf("\nScancode: 0x%h\n", scancode);
	
	if (scancode == 0x45)
	{
		led_status ^= NUM_LOCK;
   		set_leds(); //Turn on/off Num Lock led
	}
	else if (scancode == 0x3A) 
	{
		led_status ^= CAPS_LOCK;
		set_leds(); //Turn on/off Caps Lock led
	}
	else if (scancode == 0x46)
	{
		led_status ^= SCROLL_LOCK;
		set_leds(); //Turn on/off Scroll Lock led
	}
	else if (((scancode == 0x2A) || (scancode == 0x36))
			&& !(control_keys_status & SHIFT))	//If right or left Shift key pressed and not marked as pressed
	{
   		control_keys_status |= SHIFT;
	}
	else if(scancode == 0x1d)
	{
		control_keys_status |= CTRL;
	}
	else if(scancode == (0x1d | 0x80))
	{
		control_keys_status &= ~CTRL;
	}
	else if ((scancode == (0x2A + 0x80))
			|| (scancode == (0x36 + 0x80))) //If right or left Shift key depressed
	{
		control_keys_status &= (0xFF - SHIFT);
	}
	else
	{
		if (scancode & 0x80) //If a key has been depressed
		{
		}
		else if (led_status & CAPS_LOCK) //If Caps Lock on
		{
			if ((control_keys_status & SHIFT)) //If right or left Shigt key pressed
			{
				key = keyboard_layout_us_lowercase[scancode];
			}
			else
			{
				key = keyboard_layout_us_uppercase[scancode];
			}
		}
		else if ((control_keys_status & SHIFT)) //If right or left Shift key pressed
		{
			key = keyboard_layout_us_uppercase[scancode];
		}
    	else
    	{
        	key = keyboard_layout_us_lowercase[scancode];
    	}
	}
	
	if((key >= F1) && (key <= F10))
	{
		u32int i = 0;
		task_t* current = get_list_element(key - F1, task_list);
		
		if(current != LIST_ERROR)
		{
			//printf("Swithching console");
			makeVirtualConsoleFocused(current);
		}
	}
	else if((control_keys_status & CTRL) && (key == DELETE))
	{
		if(focused_task->id > 3)
			focused_task->state = KILLED;
	}
	else if (key != 0)
	{
		enqueue(key, focused_task->input_stream);
		//putChar(key);
	}
}

void set_typematic_info()
{
	while(inb(0x64) & 2);
	outb(0x60, 0xF6);
	/*u8int response;
	while((response = inb(0x64)) & 2);
	{
		printf("Response: %h\n", response & 2);
	} //Waiting for keyboard response*/
	/*while(inb(0x64) & 2);
	outb(0x60, 0x7F);
*/
}

u8int kbhit()
{
	//if (keyboard_buffer_size == 0) return 0;
	return 1;
}

void set_leds()
{
	while(inb(0x64) & 2); //Waiting for keyboard
	outb(0x60, 0xED);
	while(inb(0x64) & 2); //Waiting for keyboard
	outb(0x60, led_status);
}


